package com.practice.config;


import com.practice.security.filter.CheckTokenFilter;
import com.practice.security.handler.CustomAuthenticationFailureHandler;
import com.practice.security.verifyInfoService.CustomerUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * springSecurity配置
 * */

@Configuration   //表示该类是一个配置类
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    CheckTokenFilter checkTokenFilter;
    @Autowired
    CustomAuthenticationFailureHandler customAuthenticationFailureHandler;
    @Autowired
    CustomerUserDetailsService customerUserDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(customerUserDetailsService).passwordEncoder(passwordEncoder());
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        // 明文+随机盐值》加密存储
        return new BCryptPasswordEncoder();
    }

    /**
     * 身份验证管理器bean
     * 注入spring容器，在自定义的登录service中会调用他的authenticate方法，进行校验
     *
     * @return {@link AuthenticationManager}
     * @throws Exception 异常
     */
    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }

    /**
     * 配置权限资源和自定义认认证失败
     */
    protected void configure(HttpSecurity http) throws Exception {
        http
                // 基于token，不需要csrf,前后端分离项目天然防范CSRF攻击
                .csrf().disable()
                // 前后端分离项目大多基于 token，不需要 session
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                // 设置 jwtAuthError 处理认证失败、鉴权失败
//                .exceptionHandling().authenticationEntryPoint(jwtAuthError).accessDeniedHandler(jwtAuthError).and()
                // 下面开始设置权限
                .authorizeRequests(authorize -> authorize
                                // 对于登录接口，允许匿名访问
                                .antMatchers("/user/login").anonymous()
                                //除以上接口外，其他接口则需要鉴权认证
                                .anyRequest().authenticated()
//                        全部放开
//                        .anyRequest().permitAll()
                )
                // 添加 JWT 过滤器，JWT 过滤器在用户名密码认证过滤器之前
                .addFilterBefore(checkTokenFilter, UsernamePasswordAuthenticationFilter.class)
                //配置异常处理器
                .exceptionHandling()
                .authenticationEntryPoint(customAuthenticationFailureHandler)
//                .accessDeniedHandler(accessDeniedHandler)
                .and()
                //认证用户时用户信息加载配置，注入springAuthUserService
//                .userDetailsService(xxxAuthUserService)
                //设置允许跨域
                .cors();
    }


}
